import jwt from 'jsonwebtoken';
import { User } from '@weubi/shared';

/**
 * 测试助手工具类
 * 提供常用的测试辅助方法
 */
export class TestHelpers {
  
  // 生成JWT令牌
  static generateAccessToken(user: Partial<User>, expiresIn: string = '1h'): string {
    const payload = {
      userId: user.id,
      email: user.email,
      role: user.role || 'user'
    };

    return jwt.sign(
      payload,
      process.env.JWT_SECRET || 'test-jwt-secret',
      { expiresIn: expiresIn as any }
    );
  }

  // 生成刷新令牌
  static generateRefreshToken(userId: string, expiresIn: string = '7d'): string {
    return jwt.sign(
      { userId },
      process.env.JWT_REFRESH_SECRET || 'test-jwt-refresh-secret',
      { expiresIn: expiresIn as any }
    );
  }

  // 生成过期的令牌
  static generateExpiredToken(user: Partial<User>): string {
    return this.generateAccessToken(user, '-1h');
  }

  // 生成无效的令牌
  static generateInvalidToken(): string {
    return 'invalid.token.here';
  }

  // 创建Authorization头
  static createAuthHeader(token: string): Record<string, string> {
    return {
      'Authorization': `Bearer ${token}`
    };
  }

  // 等待指定时间
  static async wait(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  // 验证响应结构
  static validateApiResponse(response: any, expectedStatus: number = 200) {
    expect(response.status).toBe(expectedStatus);
    expect(response).toHaveProperty('success');
    
    if (response.success) {
      expect(response).toHaveProperty('data');
    } else {
      expect(response).toHaveProperty('error');
    }
  }

  // 验证用户对象结构
  static validateUserObject(user: any) {
    expect(user).toHaveProperty('id');
    expect(user).toHaveProperty('email');
    expect(user).toHaveProperty('name');
    expect(user).toHaveProperty('role');
    expect(user).toHaveProperty('isActive');
    expect(user).toHaveProperty('createdAt');
    expect(user).toHaveProperty('updatedAt');
    
    // 密码不应该被包含在响应中
    expect(user).not.toHaveProperty('password');
  }

  // 验证令牌对象结构
  static validateTokensObject(tokens: any) {
    expect(tokens).toHaveProperty('accessToken');
    expect(tokens).toHaveProperty('refreshToken');
    expect(tokens).toHaveProperty('expiresIn');
    
    expect(typeof tokens.accessToken).toBe('string');
    expect(typeof tokens.refreshToken).toBe('string');
    expect(typeof tokens.expiresIn).toBe('number');
  }

  // 验证JWT令牌格式
  static validateJwtFormat(token: string): boolean {
    const jwtRegex = /^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+$/;
    return jwtRegex.test(token);
  }

  // 解码JWT令牌（不验证签名）
  static decodeJwt(token: string): any {
    try {
      return jwt.decode(token);
    } catch (error) {
      return null;
    }
  }

  // 验证JWT令牌内容
  static validateJwtPayload(token: string, expectedUserId?: string) {
    const payload = this.decodeJwt(token);
    
    expect(payload).toBeTruthy();
    expect(payload).toHaveProperty('userId');
    expect(payload).toHaveProperty('iat');
    expect(payload).toHaveProperty('exp');
    
    if (expectedUserId) {
      expect(payload.userId).toBe(expectedUserId);
    }
    
    return payload;
  }

  // 生成随机邮箱
  static generateRandomEmail(): string {
    const timestamp = Date.now();
    const random = Math.random().toString(36).substring(7);
    return `test-${timestamp}-${random}@weubi.com`;
  }

  // 生成随机用户名
  static generateRandomName(): string {
    const adjectives = ['Smart', 'Quick', 'Bright', 'Cool', 'Fast'];
    const nouns = ['User', 'Tester', 'Developer', 'Admin', 'Guest'];
    
    const adjective = adjectives[Math.floor(Math.random() * adjectives.length)];
    const noun = nouns[Math.floor(Math.random() * nouns.length)];
    const number = Math.floor(Math.random() * 1000);
    
    return `${adjective} ${noun} ${number}`;
  }

  // 清理测试环境
  static async cleanupTestEnvironment() {
    // 这里可以添加清理逻辑
    // 比如清理临时文件、重置全局状态等
  }

  // 模拟网络延迟
  static async simulateNetworkDelay(min: number = 100, max: number = 500) {
    const delay = Math.floor(Math.random() * (max - min + 1)) + min;
    await this.wait(delay);
  }

  // 创建错误响应断言
  static expectErrorResponse(response: any, expectedStatus: number, expectedError?: string) {
    expect(response.status).toBe(expectedStatus);
    expect(response.success).toBe(false);
    expect(response).toHaveProperty('error');
    
    if (expectedError) {
      expect(response.error).toContain(expectedError);
    }
  }

  // 创建成功响应断言
  static expectSuccessResponse(response: any, expectedData?: any) {
    expect(response.success).toBe(true);
    expect(response).toHaveProperty('data');
    
    if (expectedData) {
      expect(response.data).toMatchObject(expectedData);
    }
  }
}
